1 using System;
2 using UnityEngine;
3
4 namespace ProceduralToolkit
5 {
6 /// <summary>
7 /// Collection of drawing method-independent generic drawing algorithms
8 /// </summary>
9 public static class Draw
10 {
11 public delegate void DebugDrawLine(Vector3 start, Vector3 end, Color color, float duration, bool depthTest);
12
13 private const int circleSegments = 64;
14 private const float circleSegmentAngle = 360f/circleSegments;
15
16 private static readonly Func<float, float, Vector3> pointOnCircleXY;
17 private static readonly Func<float, float, Vector3> pointOnCircleXZ;
18 private static readonly Func<float, float, Vector3> pointOnCircleYZ;
19
20 static Draw()
21 {
22 pointOnCircleXY = PTUtils.PointOnCircle3XY;
23 pointOnCircleXZ = PTUtils.PointOnCircle3XZ;
24 pointOnCircleYZ = PTUtils.PointOnCircle3YZ;
25 }
26
27 #region Raster
28
29 /// <summary>
30 /// Draws aliased line and calls <paramref name="draw"/> on every pixel
31 /// </summary>
32 /// <remarks>
33 /// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
34 /// </remarks>
35 public static void RasterLine(Vector2Int v0, Vector2Int v1, Action<int, int> draw)
36 {
37 RasterLine(v0.x, v0.y, v1.x, v1.y, draw);
38 }
39
40 /// <summary>
41 /// Draws aliased line and calls <paramref name="draw"/> on every pixel
42 /// </summary>
43 /// <remarks>
44 /// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
45 /// </remarks>
46 public static void RasterLine(int x0, int y0, int x1, int y1, Action<int, int> draw)
47 {
48 bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0);
49 if (steep)
50 {
51 PTUtils.Swap(ref x0, ref y0);
52 PTUtils.Swap(ref x1, ref y1);
53 }
54 if (x0 > x1)
55 {
56 PTUtils.Swap(ref x0, ref x1);
57 PTUtils.Swap(ref y0, ref y1);
58 }
59
60 int dx = x1 - x0;
61 int dy = Math.Abs(y1 - y0);
62 int error = dx/2;
63 int ystep = (y0 < y1) ? 1 : -1;
64 int y = y0;
65 for (int x = x0; x <= x1; x++)
66 {
67 draw(steep ? y : x, steep ? x : y);
68 error -= dy;
69 if (error < 0)
70 {
71 y += ystep;
72 error += dx;
73 }
74 }
75 }
76
77 /// <summary>
78 /// Draws anti-aliased line and calls <paramref name="draw"/> on every pixel
79 /// </summary>
80 /// <remarks>
81 /// https://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm
82 /// </remarks>
83 public static void RasterAALine(Vector2Int v0, Vector2Int v1, Action<int, int, float> draw)
84 {
85 RasterAALine(v0.x, v0.y, v1.x, v1.y, draw);
86 }
87
88 /// <summary>
89 /// Draws anti-aliased line and calls <paramref name="draw"/> on every pixel
90 /// </summary>
91 /// <remarks>
92 /// https://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm
93 /// </remarks>
94 public static void RasterAALine(int x0, int y0, int x1, int y1, Action<int, int, float> draw)
95 {
96 bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0);
97 if (steep)
98 {
99 PTUtils.Swap(ref x0, ref y0);
100 PTUtils.Swap(ref x1, ref y1);
101 }
102 if (x0 > x1)
103 {
104 PTUtils.Swap(ref x0, ref x1);
105 PTUtils.Swap(ref y0, ref y1);
106 }
107
108 if (steep)
109 {
110 draw(y0, x0, 1);
111 draw(y1, x1, 1);
112 }
113 else
114 {
115 draw(x0, y0, 1);
116 draw(x1, y1, 1);
117 }
118 float dx = x1 - x0;
119 float dy = y1 - y0;
120 float gradient = dy/dx;
121 float y = y0 + gradient;
122 for (var x = x0 + 1; x <= x1 - 1; x++)
123 {
124 if (steep)
125 {
126 draw((int) y, x, 1 - (y - (int) y));
127 draw((int) y + 1, x, y - (int) y);
128 }
129 else
130 {
131 draw(x, (int) y, 1 - (y - (int) y));
132 draw(x, (int) y + 1, y - (int) y);
133 }
134 y += gradient;
135 }
136 }
137
138 /// <summary>
139 /// Draws aliased circle and calls <paramref name="draw"/> on every pixel
140 /// </summary>
141 /// <remarks>
142 /// A Rasterizing Algorithm for Drawing Curves
143 /// http://members.chello.at/easyfilter/bresenham.pdf
144 /// </remarks>
145 public static void RasterCircle(Vector2Int v0, int radius, Action<int, int> draw)
146 {
147 RasterCircle(v0.x, v0.y, radius, draw);
148 }
149
150 /// <summary>
151 /// Draws aliased circle and calls <paramref name="draw"/> on every pixel
152 /// </summary>
153 /// <remarks>
154 /// A Rasterizing Algorithm for Drawing Curves
155 /// http://members.chello.at/easyfilter/bresenham.pdf
156 /// </remarks>
157 public static void RasterCircle(int x0, int y0, int radius, Action<int, int> draw)
158 {
159 int x = -radius;
160 int y = 0;
161 int error = 2 - 2*radius; // 2 quadrant ◴
162 while (x < 0)
163 {
164 draw(x0 - x, y0 + y); // 1 quadrant ◷
165 draw(x0 - y, y0 - x); // 2 quadrant ◴
166 draw(x0 + x, y0 - y); // 3 quadrant ◵
167 draw(x0 + y, y0 + x); // 4 quadrant ◶
168
169 int lastError = error;
170 if (y >= error)
171 {
172 y++;
173 error += 2*y + 1;
174 }
175
176 // Second check is needed to avoid weird pixels at diagonals at some radiuses
177 // Example radiuses: 4, 11, 134, 373, 4552
178 if (x < lastError || y < error)
179 {
180 x++;
181 error += 2*x + 1;
182 }
183 }
184 }
185
186 /// <summary>
187 /// Draws filled aliased circle and calls <paramref name="draw"/> on every pixel
188 /// </summary>
189 public static void RasterFilledCircle(Vector2Int v0, int radius, Action<int, int> draw)
190 {
191 RasterFilledCircle(v0.x, v0.y, radius, draw);
192 }
193
194 /// <summary>
195 /// Draws filled aliased circle and calls <paramref name="draw"/> on every pixel
196 /// </summary>
197 public static void RasterFilledCircle(int x0, int y0, int radius, Action<int, int> draw)
198 {
199 int x = -radius;
200 int y = 0;
201 int error = 2 - 2*radius; // 2 quadrant ◴
202 // lastY must have a different value than y
203 int lastY = Int32.MaxValue;
204 while (x < 0)
205 {
206 // This check prevents overdraw at poles
207 if (lastY != y)
208 {
209 DrawHorizontalLine(x0 + x, x0 - x, y0 + y, draw); // ◠
210 // This check prevents overdraw at central horizontal
211 if (y != 0)
212 {
213 DrawHorizontalLine(x0 + x, x0 - x, y0 - y, draw); // ◡
214 }
215 }
216 lastY = y;
217
218 int lastError = error;
219 if (y >= error)
220 {
221 y++;
222 error += 2*y + 1;
223 }
224
225 // Second check is needed to avoid weird pixels at diagonals at some radiuses
226 // Example radiuses: 4, 11, 134, 373, 4552
227 if (x < lastError || y < error)
228 {
229 x++;
230 error += 2*x + 1;
231 }
232 }
233 }
234
235 private static void DrawHorizontalLine(int fromX, int toX, int y, Action<int, int> draw)
236 {
237 for (int x = fromX; x <= toX; x++)
238 {
239 draw(x, y);
240 }
241 }
242
243 #endregion Raster
244
245 public static void WireRay(Action<Vector3, Vector3> drawLine, Ray ray)
246 {
247 drawLine(ray.origin, ray.origin + ray.direction);
248 }
249
250 public static void WireRay(
251 DebugDrawLine drawLine,
252 Ray ray,
253 Color color,
254 float duration,
255 bool depthTest)
256 {
257 drawLine(ray.origin, ray.origin + ray.direction, color, duration, depthTest);
258 }
259
260 #region WireQuad
261
262 public static void WireQuadXY(
263 Action<Vector3, Vector3> drawLine,
264 Vector3 position,
265 Quaternion rotation,
266 Vector2 scale)
267 {
268 WireQuad(drawLine, position, rotation, scale, Vector3.right, Vector3.up);
269 }
270
271 public static void WireQuadXY(
272 DebugDrawLine drawLine,
273 Vector3 position,
274 Quaternion rotation,
275 Vector2 scale,
276 Color color,
277 float duration,
278 bool depthTest)
279 {
280 WireQuad(drawLine, position, rotation, scale, Vector3.right, Vector3.up, color, duration, depthTest);
281 }
282
283 public static void WireQuadXZ(
284 Action<Vector3, Vector3> drawLine,
285 Vector3 position,
286 Quaternion rotation,
287 Vector2 scale)
288 {
289 WireQuad(drawLine, position, rotation, scale, Vector3.right, Vector3.forward);
290 }
291
292 public static void WireQuadXZ(
293 DebugDrawLine drawLine,
294 Vector3 position,
295 Quaternion rotation,
296 Vector2 scale,
297 Color color,
298 float duration,
299 bool depthTest)
300 {
301 WireQuad(drawLine, position, rotation, scale, Vector3.right, Vector3.forward, color, duration, depthTest);
302 }
303
304 public static void WireQuadYZ(
305 Action<Vector3, Vector3> drawLine,
306 Vector3 position,
307 Quaternion rotation,
308 Vector2 scale)
309 {
310 WireQuad(drawLine, position, rotation, scale, Vector3.up, Vector3.forward);
311 }
312
313 public static void WireQuadYZ(
314 DebugDrawLine drawLine,
315 Vector3 position,
316 Quaternion rotation,
317 Vector2 scale,
318 Color color,
319 float duration,
320 bool depthTest)
321 {
322 WireQuad(drawLine, position, rotation, scale, Vector3.up, Vector3.forward, color, duration, depthTest);
323 }
324
325 public static void WireQuad(
326 Action<Vector3, Vector3> drawLine,
327 Vector3 position,
328 Quaternion rotation,
329 Vector2 scale,
330 Vector3 planeRight,
331 Vector3 planeForward)
332 {
333 Vector3 right = rotation*planeRight*scale.x;
334 Vector3 forward = rotation*planeForward*scale.y;
335 Vector3 forwardRight = position + right*0.5f + forward*0.5f;
336 Vector3 backRight = forwardRight - forward;
337 Vector3 backLeft = backRight - right;
338 Vector3 forwardLeft = forwardRight - right;
339
340 drawLine(forwardRight, backRight);
341 drawLine(backRight, backLeft);
342 drawLine(backLeft, forwardLeft);
343 drawLine(forwardLeft, forwardRight);
344 }
345
346 public static void WireQuad(
347 DebugDrawLine drawLine,
348 Vector3 position,
349 Quaternion rotation,
350 Vector2 scale,
351 Vector3 planeRight,
352 Vector3 planeForward,
353 Color color,
354 float duration,
355 bool depthTest)
356 {
357 Vector3 right = rotation*planeRight*scale.x;
358 Vector3 forward = rotation*planeForward*scale.y;
359 Vector3 forwardRight = position + right*0.5f + forward*0.5f;
360 Vector3 backRight = forwardRight - forward;
361 Vector3 backLeft = backRight - right;
362 Vector3 forwardLeft = forwardRight - right;
363
364 drawLine(forwardRight, backRight, color, duration, depthTest);
365 drawLine(backRight, backLeft, color, duration, depthTest);
366 drawLine(backLeft, forwardLeft, color, duration, depthTest);
367 drawLine(forwardLeft, forwardRight, color, duration, depthTest);
368 }
369
370 #endregion WireQuad
371
372 public static void WireCube(
373 Action<Vector3, Vector3> drawLine,
374 Vector3 position,
375 Quaternion rotation,
376 Vector3 scale)
377 {
378 Vector3 right = rotation*Vector3.right*scale.x;
379 Vector3 up = rotation*Vector3.up*scale.y;
380 Vector3 forward = rotation*Vector3.forward*scale.z;
381
382 Vector3 a1 = position + right*0.5f + up*0.5f + forward*0.5f;
383 Vector3 b1 = a1 - up;
384 Vector3 c1 = b1 - right;
385 Vector3 d1 = a1 - right;
386
387 Vector3 a2 = a1 - forward;
388 Vector3 b2 = b1 - forward;
389 Vector3 c2 = c1 - forward;
390 Vector3 d2 = d1 - forward;
391
392 drawLine(a1, b1);
393 drawLine(b1, c1);
394 drawLine(c1, d1);
395 drawLine(d1, a1);
396
397 drawLine(a2, b2);
398 drawLine(b2, c2);
399 drawLine(c2, d2);
400 drawLine(d2, a2);
401
402 drawLine(a1, a2);
403 drawLine(b1, b2);
404 drawLine(c1, c2);
405 drawLine(d1, d2);
406 }
407
408 public static void WireCube(
409 DebugDrawLine drawLine,
410 Vector3 position,
411 Quaternion rotation,
412 Vector3 scale,
413 Color color,
414 float duration,
415 bool depthTest)
416 {
417 Vector3 right = rotation*Vector3.right*scale.x;
418 Vector3 up = rotation*Vector3.up*scale.y;
419 Vector3 forward = rotation*Vector3.forward*scale.z;
420
421 Vector3 a1 = position + right*0.5f + up*0.5f + forward*0.5f;
422 Vector3 b1 = a1 - up;
423 Vector3 c1 = b1 - right;
424 Vector3 d1 = a1 - right;
425
426 Vector3 a2 = a1 - forward;
427 Vector3 b2 = b1 - forward;
428 Vector3 c2 = c1 - forward;
429 Vector3 d2 = d1 - forward;
430
431 drawLine(a1, b1, color, duration, depthTest);
432 drawLine(b1, c1, color, duration, depthTest);
433 drawLine(c1, d1, color, duration, depthTest);
434 drawLine(d1, a1, color, duration, depthTest);
435
436 drawLine(a2, b2, color, duration, depthTest);
437 drawLine(b2, c2, color, duration, depthTest);
438 drawLine(c2, d2, color, duration, depthTest);
439 drawLine(d2, a2, color, duration, depthTest);
440
441 drawLine(a1, a2, color, duration, depthTest);
442 drawLine(b1, b2, color, duration, depthTest);
443 drawLine(c1, c2, color, duration, depthTest);
444 drawLine(d1, d2, color, duration, depthTest);
445 }
446
447 #region WireCircleXY
448
449 public static void WireCircleXY(
450 Action<Vector3, Vector3> drawLine,
451 Vector3 position,
452 float radius)
453 {
454 WireCircle(pointOnCircleXY, drawLine, position, radius);
455 }
456
457 public static void WireCircleXY(
458 DebugDrawLine drawLine,
459 Vector3 position,
460 float radius,
461 Color color,
462 float duration,
463 bool depthTest)
464 {
465 WireCircle(pointOnCircleXY, drawLine, position, radius, color, duration, depthTest);
466 }
467
468 public static void WireCircleXY(
469 Action<Vector3, Vector3> drawLine,
470 Vector3 position,
471 Quaternion rotation,
472 float radius)
473 {
474 WireCircle(pointOnCircleXY, drawLine, position, rotation, radius);
475 }
476
477 public static void WireCircleXY(
478 DebugDrawLine drawLine,
479 Vector3 position,
480 Quaternion rotation,
481 float radius,
482 Color color,
483 float duration,
484 bool depthTest)
485 {
486 WireCircle(pointOnCircleXY, drawLine, position, rotation, radius, color, duration, depthTest);
487 }
488
489 #endregion WireCircleXY
490
491 #region WireCircleXZ
492
493 public static void WireCircleXZ(
494 Action<Vector3, Vector3> drawLine,
495 Vector3 position,
496 float radius)
497 {
498 WireCircle(pointOnCircleXZ, drawLine, position, radius);
499 }
500
501 public static void WireCircleXZ(
502 DebugDrawLine drawLine,
503 Vector3 position,
504 float radius,
505 Color color,
506 float duration,
507 bool depthTest)
508 {
509 WireCircle(pointOnCircleXZ, drawLine, position, radius, color, duration, depthTest);
510 }
511
512 public static void WireCircleXZ(
513 Action<Vector3, Vector3> drawLine,
514 Vector3 position,
515 Quaternion rotation,
516 float radius)
517 {
518 WireCircle(pointOnCircleXZ, drawLine, position, rotation, radius);
519 }
520
521 public static void WireCircleXZ(
522 DebugDrawLine drawLine,
523 Vector3 position,
524 Quaternion rotation,
525 float radius,
526 Color color,
527 float duration,
528 bool depthTest)
529 {
530 WireCircle(pointOnCircleXZ, drawLine, position, rotation, radius, color, duration, depthTest);
531 }
532
533 #endregion WireCircleXZ
534
535 #region WireCircleYZ
536
537 public static void WireCircleYZ(
538 Action<Vector3, Vector3> drawLine,
539 Vector3 position,
540 float radius)
541 {
542 WireCircle(pointOnCircleYZ, drawLine, position, radius);
543 }
544
545 public static void WireCircleYZ(
546 DebugDrawLine drawLine,
547 Vector3 position,
548 float radius,
549 Color color,
550 float duration,
551 bool depthTest)
552 {
553 WireCircle(pointOnCircleYZ, drawLine, position, radius, color, duration, depthTest);
554 }
555
556 public static void WireCircleYZ(
557 Action<Vector3, Vector3> drawLine,
558 Vector3 position,
559 Quaternion rotation,
560 float radius)
561 {
562 WireCircle(pointOnCircleYZ, drawLine, position, rotation, radius);
563 }
564
565 public static void WireCircleYZ(
566 DebugDrawLine drawLine,
567 Vector3 position,
568 Quaternion rotation,
569 float radius,
570 Color color,
571 float duration,
572 bool depthTest)
573 {
574 WireCircle(pointOnCircleYZ, drawLine, position, rotation, radius, color, duration, depthTest);
575 }
576
577 #endregion WireCircleYZ
578
579 #region WireCircle Universal
580
581 public static void WireCircle(
582 Func<float, float, Vector3> pointOnCircle,
583 Action<Vector3, Vector3> drawLine,
584 Vector3 position,
585 float radius)
586 {
587 WireArc(pointOnCircle, drawLine, position, radius, 0, circleSegments, circleSegmentAngle);
588 }
589
590 public static void WireCircle(
591 Func<float, float, Vector3> pointOnCircle,
592 DebugDrawLine drawLine,
593 Vector3 position,
594 float radius,
595 Color color,
596 float duration,
597 bool depthTest)
598 {
599 WireArc(pointOnCircle, drawLine, position, radius, 0, circleSegments, circleSegmentAngle, color, duration,
600 depthTest);
601 }
602
603 public static void WireCircle(
604 Func<float, float, Vector3> pointOnCircle,
605 Action<Vector3, Vector3> drawLine,
606 Vector3 position,
607 Quaternion rotation,
608 float radius)
609 {
610 WireArc(pointOnCircle, drawLine, position, rotation, radius, 0, circleSegments, circleSegmentAngle);
611 }
612
613 public static void WireCircle(
614 Func<float, float, Vector3> pointOnCircle,
615 DebugDrawLine drawLine,
616 Vector3 position,
617 Quaternion rotation,
618 float radius,
619 Color color,
620 float duration,
621 bool depthTest)
622 {
623 WireArc(pointOnCircle, drawLine, position, rotation, radius, 0, circleSegments, circleSegmentAngle, color,
624 duration, depthTest);
625 }
626
627 #endregion WireCircle Universal
628
629 #region WireArcXY
630
631 public static void WireArcXY(
632 Action<Vector3, Vector3> drawLine,
633 Vector3 position,
634 float radius,
635 float fromAngle,
636 float toAngle)
637 {
638 WireArc(pointOnCircleXY, drawLine, position, radius, fromAngle, toAngle);
639 }
640
641 public static void WireArcXY(
642 DebugDrawLine drawLine,
643 Vector3 position,
644 float radius,
645 float fromAngle,
646 float toAngle,
647 Color color,
648 float duration,
649 bool depthTest)
650 {
651 WireArc(pointOnCircleXY, drawLine, position, radius, fromAngle, toAngle, color, duration, depthTest);
652 }
653
654 public static void WireArcXY(
655 Action<Vector3, Vector3> drawLine,
656 Vector3 position,
657 Quaternion rotation,
658 float radius,
659 float fromAngle,
660 float toAngle)
661 {
662 WireArc(pointOnCircleXY, drawLine, position, rotation, radius, fromAngle, toAngle);
663 }
664
665 public static void WireArcXY(
666 DebugDrawLine drawLine,
667 Vector3 position,
668 Quaternion rotation,
669 float radius,
670 float fromAngle,
671 float toAngle,
672 Color color,
673 float duration,
674 bool depthTest)
675 {
676 WireArc(pointOnCircleXY, drawLine, position, rotation, radius, fromAngle, toAngle, color, duration,
677 depthTest);
678 }
679
680 #endregion WireCircleXY
681
682 #region WireArcXZ
683
684 public static void WireArcXZ(
685 Action<Vector3, Vector3> drawLine,
686 Vector3 position,
687 float radius,
688 float fromAngle,
689 float toAngle)
690 {
691 WireArc(pointOnCircleXZ, drawLine, position, radius, fromAngle, toAngle);
692 }
693
694 public static void WireArcXZ(
695 DebugDrawLine drawLine,
696 Vector3 position,
697 float radius,
698 float fromAngle,
699 float toAngle,
700 Color color,
701 float duration,
702 bool depthTest)
703 {
704 WireArc(pointOnCircleXZ, drawLine, position, radius, fromAngle, toAngle, color, duration, depthTest);
705 }
706
707 public static void WireArcXZ(
708 Action<Vector3, Vector3> drawLine,
709 Vector3 position,
710 Quaternion rotation,
711 float radius,
712 float fromAngle,
713 float toAngle)
714 {
715 WireArc(pointOnCircleXZ, drawLine, position, rotation, radius, fromAngle, toAngle);
716 }
717
718 public static void WireArcXZ(
719 DebugDrawLine drawLine,
720 Vector3 position,
721 Quaternion rotation,
722 float radius,
723 float fromAngle,
724 float toAngle,
725 Color color,
726 float duration,
727 bool depthTest)
728 {
729 WireArc(pointOnCircleXZ, drawLine, position, rotation, radius, fromAngle, toAngle, color, duration,
730 depthTest);
731 }
732
733 #endregion WireCircleXZ
734
735 #region WireArcYZ
736
737 public static void WireArcYZ(
738 Action<Vector3, Vector3> drawLine,
739 Vector3 position,
740 float radius,
741 float fromAngle,
742 float toAngle)
743 {
744 WireArc(pointOnCircleYZ, drawLine, position, radius, fromAngle, toAngle);
745 }
746
747 public static void WireArcYZ(
748 DebugDrawLine drawLine,
749 Vector3 position,
750 float radius,
751 float fromAngle,
752 float toAngle,
753 Color color,
754 float duration,
755 bool depthTest)
756 {
757 WireArc(pointOnCircleYZ, drawLine, position, radius, fromAngle, toAngle, color, duration, depthTest);
758 }
759
760 public static void WireArcYZ(
761 Action<Vector3, Vector3> drawLine,
762 Vector3 position,
763 Quaternion rotation,
764 float radius,
765 float fromAngle,
766 float toAngle)
767 {
768 WireArc(pointOnCircleYZ, drawLine, position, rotation, radius, fromAngle, toAngle);
769 }
770
771 public static void WireArcYZ(
772 DebugDrawLine drawLine,
773 Vector3 position,
774 Quaternion rotation,
775 float radius,
776 float fromAngle,
777 float toAngle,
778 Color color,
779 float duration,
780 bool depthTest)
781 {
782 WireArc(pointOnCircleYZ, drawLine, position, rotation, radius, fromAngle, toAngle, color, duration,
783 depthTest);
784 }
785
786 #endregion WireCircleYZ
787
788 #region WireArc Universal
789
790 public static void WireArc(
791 Func<float, float, Vector3> pointOnCircle,
792 Action<Vector3, Vector3> drawLine,
793 Vector3 position,
794 float radius,
795 float fromAngle,
796 float toAngle)
797 {
798 int segments;
799 float segmentAngle;
800 GetSegmentsAndSegmentAngle(fromAngle, toAngle, out segments, out segmentAngle);
801
802 WireArc(pointOnCircle, drawLine, position, radius, fromAngle, segments, segmentAngle);
803 }
804
805 public static void WireArc(
806 Func<float, float, Vector3> pointOnCircle,
807 DebugDrawLine drawLine,
808 Vector3 position,
809 float radius,
810 float fromAngle,
811 float toAngle,
812 Color color,
813 float duration,
814 bool depthTest)
815 {
816 int segments;
817 float segmentAngle;
818 GetSegmentsAndSegmentAngle(fromAngle, toAngle, out segments, out segmentAngle);
819
820 WireArc(pointOnCircle, drawLine, position, radius, fromAngle, segments, segmentAngle, color, duration,
821 depthTest);
822 }
823
824 public static void WireArc(
825 Func<float, float, Vector3> pointOnCircle,
826 Action<Vector3, Vector3> drawLine,
827 Vector3 position,
828 Quaternion rotation,
829 float radius,
830 float fromAngle,
831 float toAngle)
832 {
833 int segments;
834 float segmentAngle;
835 GetSegmentsAndSegmentAngle(fromAngle, toAngle, out segments, out segmentAngle);
836
837 WireArc(pointOnCircle, drawLine, position, rotation, radius, fromAngle, segments, segmentAngle);
838 }
839
840 public static void WireArc(
841 Func<float, float, Vector3> pointOnCircle,
842 DebugDrawLine drawLine,
843 Vector3 position,
844 Quaternion rotation,
845 float radius,
846 float fromAngle,
847 float toAngle,
848 Color color,
849 float duration,
850 bool depthTest)
851 {
852 int segments;
853 float segmentAngle;
854 GetSegmentsAndSegmentAngle(fromAngle, toAngle, out segments, out segmentAngle);
855
856 WireArc(pointOnCircle, drawLine, position, rotation, radius, fromAngle, segments, segmentAngle, color,
857 duration, depthTest);
858 }
859
860 public static void WireArc(
861 Func<float, float, Vector3> pointOnCircle,
862 Action<Vector3, Vector3> drawLine,
863 Vector3 position,
864 float radius,
865 float fromAngle,
866 int segments,
867 float segmentAngle)
868 {
869 float currentAngle = fromAngle;
870 for (var i = 0; i < segments; i++)
871 {
872 Vector3 a = position + pointOnCircle(radius, currentAngle);
873 currentAngle += segmentAngle;
874 Vector3 b = position + pointOnCircle(radius, currentAngle);
875 drawLine(a, b);
876 }
877 }
878
879 public static void WireArc(
880 Func<float, float, Vector3> pointOnCircle,
881 DebugDrawLine drawLine,
882 Vector3 position,
883 float radius,
884 float fromAngle,
885 int segments,
886 float segmentAngle,
887 Color color,
888 float duration,
889 bool depthTest)
890 {
891 float currentAngle = fromAngle;
892 for (var i = 0; i < segments; i++)
893 {
894 Vector3 a = position + pointOnCircle(radius, currentAngle);
895 currentAngle += segmentAngle;
896 Vector3 b = position + pointOnCircle(radius, currentAngle);
897 drawLine(a, b, color, duration, depthTest);
898 }
899 }
900
901 public static void WireArc(
902 Func<float, float, Vector3> pointOnCircle,
903 Action<Vector3, Vector3> drawLine,
904 Vector3 position,
905 Quaternion rotation,
906 float radius,
907 float fromAngle,
908 int segments,
909 float segmentAngle)
910 {
911 float currentAngle = fromAngle;
912 for (var i = 0; i < segments; i++)
913 {
914 Vector3 a = position + rotation*pointOnCircle(radius, currentAngle);
915 currentAngle += segmentAngle;
916 Vector3 b = position + rotation*pointOnCircle(radius, currentAngle);
917 drawLine(a, b);
918 }
919 }
920
921 public static void WireArc(
922 Func<float, float, Vector3> pointOnCircle,
923 DebugDrawLine drawLine,
924 Vector3 position,
925 Quaternion rotation,
926 float radius,
927 float fromAngle,
928 int segments,
929 float segmentAngle,
930 Color color,
931 float duration,
932 bool depthTest)
933 {
934 float currentAngle = fromAngle;
935 for (var i = 0; i < segments; i++)
936 {
937 Vector3 a = position + rotation*pointOnCircle(radius, currentAngle);
938 currentAngle += segmentAngle;
939 Vector3 b = position + rotation*pointOnCircle(radius, currentAngle);
940 drawLine(a, b, color, duration, depthTest);
941 }
942 }
943
944 #endregion WireArc Universal
945
946 public static void WireSphere(
947 Action<Vector3, Vector3> drawLine,
948 Vector3 position,
949 Quaternion rotation,
950 float radius)
951 {
952 WireCircleXY(drawLine, position, rotation, radius);
953 WireCircleXZ(drawLine, position, rotation, radius);
954 WireCircleYZ(drawLine, position, rotation, radius);
955 }
956
957 public static void WireSphere(
958 DebugDrawLine drawLine,
959 Vector3 position,
960 Quaternion rotation,
961 float radius,
962 Color color,
963 float duration,
964 bool depthTest)
965 {
966 WireCircleXY(drawLine, position, rotation, radius, color, duration, depthTest);
967 WireCircleXZ(drawLine, position, rotation, radius, color, duration, depthTest);
968 WireCircleYZ(drawLine, position, rotation, radius, color, duration, depthTest);
969 }
970
971 public static void WireHemisphere(
972 Action<Vector3, Vector3> drawLine,
973 Vector3 position,
974 Quaternion rotation,
975 float radius)
976 {
977 WireArcXY(drawLine, position, rotation, radius, -90, 90);
978 WireCircleXZ(drawLine, position, rotation, radius);
979 WireArcYZ(drawLine, position, rotation, radius, 0, 180);
980 }
981
982 public static void WireHemisphere(
983 DebugDrawLine drawLine,
984 Vector3 position,
985 Quaternion rotation,
986 float radius,
987 Color color,
988 float duration,
989 bool depthTest)
990 {
991 WireArcXY(drawLine, position, rotation, radius, -90, 90, color, duration, depthTest);
992 WireCircleXZ(drawLine, position, rotation, radius, color, duration, depthTest);
993 WireArcYZ(drawLine, position, rotation, radius, 0, 180, color, duration, depthTest);
994 }
995
996 public static void WireCone(
997 Action<Vector3, Vector3> drawLine,
998 Vector3 position,
999 Quaternion rotation,
1000 float apexRadius,
1001 float angle,
1002 float length)
1003 {
1004 Vector3 upperCenter = position + rotation*Vector3.up*length;
1005 float upperRadius = Mathf.Tan(angle*Mathf.Deg2Rad)*length + apexRadius;
1006 WireCircleXZ(drawLine, upperCenter, rotation, upperRadius);
1007
1008 Vector3 a2 = upperCenter + rotation*PTUtils.PointOnCircle3XZ(upperRadius, 0);
1009 Vector3 b2 = upperCenter + rotation*PTUtils.PointOnCircle3XZ(upperRadius, 90);
1010 Vector3 c2 = upperCenter + rotation*PTUtils.PointOnCircle3XZ(upperRadius, 180);
1011 Vector3 d2 = upperCenter + rotation*PTUtils.PointOnCircle3XZ(upperRadius, 270);
1012
1013 if (apexRadius == 0)
1014 {
1015 drawLine(position, a2);
1016 drawLine(position, b2);
1017 drawLine(position, c2);
1018 drawLine(position, d2);
1019 }
1020 else
1021 {
1022 WireCircleXZ(drawLine, position, rotation, apexRadius);
1023
1024 Vector3 a1 = rotation*PTUtils.PointOnCircle3XZ(apexRadius, 0);
1025 Vector3 b1 = rotation*PTUtils.PointOnCircle3XZ(apexRadius, 90);
1026 Vector3 c1 = rotation*PTUtils.PointOnCircle3XZ(apexRadius, 180);
1027 Vector3 d1 = rotation*PTUtils.PointOnCircle3XZ(apexRadius, 270);
1028
1029 drawLine(a1, a2);
1030 drawLine(b1, b2);
1031 drawLine(c1, c2);
1032 drawLine(d1, d2);
1033 }
1034 }
1035
1036 public static void WireCone(
1037 DebugDrawLine drawLine,
1038 Vector3 position,
1039 Quaternion rotation,
1040 float apexRadius,
1041 float angle,
1042 float length,
1043 Color color,
1044 float duration,
1045 bool depthTest)
1046 {
1047 Vector3 upperCenter = position + rotation*Vector3.up*length;
1048 float upperRadius = Mathf.Tan(angle*Mathf.Deg2Rad)*length + apexRadius;
1049 WireCircleXZ(drawLine, upperCenter, rotation, upperRadius, color, duration, depthTest);
1050
1051 Vector3 a2 = upperCenter + rotation*PTUtils.PointOnCircle3XZ(upperRadius, 0);
1052 Vector3 b2 = upperCenter + rotation*PTUtils.PointOnCircle3XZ(upperRadius, 90);
1053 Vector3 c2 = upperCenter + rotation*PTUtils.PointOnCircle3XZ(upperRadius, 180);
1054 Vector3 d2 = upperCenter + rotation*PTUtils.PointOnCircle3XZ(upperRadius, 270);
1055
1056 if (apexRadius == 0)
1057 {
1058 drawLine(position, a2, color, duration, depthTest);
1059 drawLine(position, b2, color, duration, depthTest);
1060 drawLine(position, c2, color, duration, depthTest);
1061 drawLine(position, d2, color, duration, depthTest);
1062 }
1063 else
1064 {
1065 WireCircleXZ(drawLine, position, rotation, apexRadius, color, duration, depthTest);
1066
1067 Vector3 a1 = rotation*PTUtils.PointOnCircle3XZ(apexRadius, 0);
1068 Vector3 b1 = rotation*PTUtils.PointOnCircle3XZ(apexRadius, 90);
1069 Vector3 c1 = rotation*PTUtils.PointOnCircle3XZ(apexRadius, 180);
1070 Vector3 d1 = rotation*PTUtils.PointOnCircle3XZ(apexRadius, 270);
1071
1072 drawLine(a1, a2, color, duration, depthTest);
1073 drawLine(b1, b2, color, duration, depthTest);
1074 drawLine(c1, c2, color, duration, depthTest);
1075 drawLine(d1, d2, color, duration, depthTest);
1076 }
1077 }
1078
1079 private static void GetSegmentsAndSegmentAngle(
1080 float fromAngle,
1081 float toAngle,
1082 out int segments,
1083 out float segmentAngle)
1084 {
1085 float range = toAngle - fromAngle;
1086 if (range > circleSegmentAngle)
1087 {
1088 segments = Mathf.FloorToInt(range/circleSegmentAngle);
1089 segmentAngle = range/segments;
1090 }
1091 else
1092 {
1093 segments = 1;
1094 segmentAngle = range;
1095 }
1096 }
1097 }
1098 }